package cn.wmw.xyy.service.impl;

import cn.wmw.result.PageList;
import cn.wmw.xyy.doc.CourseDoc;
import cn.wmw.xyy.dto.EsCourseSearchDto;
import cn.wmw.xyy.repository.CourseRepository;
import cn.wmw.xyy.service.IEsCourseService;
import cn.wmw.xyy.utils.EsPageList;
import cn.wmw.xyy.utils.HighlightResultMapper;
import cn.wmw.xyy.vo.CourseAggResultVo;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class EsCourseServiceImpl implements IEsCourseService {

    @Autowired
    private CourseRepository courseRepository;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private HighlightResultMapper highlightResultMapper;

    /**
     * 新增课程
     * @param courseDoc
     */
    @Override
    public void save(CourseDoc courseDoc) {
        courseRepository.save(courseDoc);
    }

    @Override
    public PageList<CourseDoc> search(EsCourseSearchDto courseSearchDto) {
        String chargeName = courseSearchDto.getChargeName();
        Long courseTypeId = courseSearchDto.getCourseTypeId();
        String gradeName = courseSearchDto.getGradeName();
        String keyword = courseSearchDto.getKeyword();
        BigDecimal priceMax = courseSearchDto.getPriceMax();
        BigDecimal priceMin = courseSearchDto.getPriceMin();
        Integer rows = courseSearchDto.getRows();
        String sortField = courseSearchDto.getSortField();
        String sortType = courseSearchDto.getSortType();
        Integer page = courseSearchDto.getPage();

        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        // 设置查询
        if (!StringUtils.isEmpty(keyword)){
            boolQueryBuilder.filter(QueryBuilders.matchQuery("name",keyword.trim()));
        }
        if (!StringUtils.isEmpty(courseTypeId)){
            boolQueryBuilder.filter(QueryBuilders.termQuery("courseTypeId", courseTypeId));
        }
        if (!StringUtils.isEmpty(gradeName)){
            boolQueryBuilder.filter(QueryBuilders.termQuery("gradeName", gradeName));
        }
        if (!StringUtils.isEmpty(chargeName)){
            boolQueryBuilder.filter(QueryBuilders.termQuery("chargeName", chargeName));
        }
        if (!StringUtils.isEmpty(priceMin)){
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(priceMin));
        }
        if (!StringUtils.isEmpty(priceMax)){
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(priceMax));
        }

        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);

        nativeSearchQueryBuilder.withHighlightFields(new HighlightBuilder.Field("name").preTags("<i style='color:blue'>").postTags("</i>"));

        //排序
        if (!StringUtils.isEmpty(sortField) && !StringUtils.isEmpty(sortType)){
            SortOrder sortOrder = "asc".equals(sortType)?SortOrder.ASC:SortOrder.DESC;
            nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort(sortField).order(sortOrder));
        }
        //分页
        nativeSearchQueryBuilder.withPageable(PageRequest.of(page,rows));
        //设置等级和收费查询
        nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("gradeNameTermsAgg").field("gradeName"));
        nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("chargeNameTermsAgg").field("chargeName"));
        NativeSearchQuery nativeSearchQuery = nativeSearchQueryBuilder.build();
        AggregatedPage<CourseDoc> courseDocs = elasticsearchRestTemplate.queryForPage(nativeSearchQuery, CourseDoc.class, highlightResultMapper);
        Aggregations aggregations = courseDocs.getAggregations();
        Map<String, Aggregation> asMap = aggregations.getAsMap();
        HashMap<String, List<CourseAggResultVo>> map = new HashMap<>();
        asMap.entrySet().forEach(e->{
            String key = e.getKey();
            List<? extends Terms.Bucket> buckets = ((ParsedStringTerms) e.getValue()).getBuckets();
            List<CourseAggResultVo> aggs = new ArrayList<>();
            buckets.forEach(b->{
                Object chargeKey = b.getKey();
                long docCount = b.getDocCount();
                CourseAggResultVo courseAggResultVo = new CourseAggResultVo(chargeKey.toString(), docCount);
                aggs.add(courseAggResultVo);
            });
            map.put(key, aggs);

        });
        return new EsPageList(courseDocs.getTotalElements(), courseDocs.getContent(), map);
    }
}
